package com.he.controller;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.he.common.Constants;
import com.he.common.Result;
import com.he.dto.UserDTO;
import com.he.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.List;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.he.entity.User;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

/**
 *  用户控制器
 * @author KrisHee
 * @since 2022-04-30
 */
@RestController
@RequestMapping("/user")
public class UserController {

        @Autowired
        private UserService userService;

        @Resource
        private StringRedisTemplate stringRedisTemplate;

        public String USER_KEY = "USER_FIND_All";

        // 新增和修改
        @PostMapping
        public Result save(@RequestBody User user) {
                // 新增或者更新
                return Result.success(userService.saveOrUpdate(user));
        }

        // 查询所有数据
        @GetMapping
        public Result findAll() {
                // 1.从缓存中获取数据
                String jsonStr = stringRedisTemplate.opsForValue().get(USER_KEY);
                List<User> files;
                //缓存为空
                if (StrUtil.isBlank(jsonStr)){
                        //从数据库取出数据
                         files = userService.list();
                         //再缓存到Redis
                        stringRedisTemplate.opsForValue().set("USER_KEY",JSONUtil.toJsonStr(files));
                }else{
                        //从Redis缓存中获取数据
                         files = JSONUtil.toBean(jsonStr,  new TypeReference<List<User>>(){}, true);
                }
                return Result.success(files);
        }

        @GetMapping("/role/{role}")
        public Result findUsersByRole(@PathVariable String role) {
                QueryWrapper<User> objectQueryWrapper = new QueryWrapper<>();
                objectQueryWrapper.eq("role",role);
                List<User> list = userService.list(objectQueryWrapper);
                return Result.success(list);
        }

        // 删除用户信息
        @DeleteMapping("/{id}")
        public boolean delete(@PathVariable Integer id) {
                return userService.removeById(id);
        }

        // 批量删除用户信息
        @PostMapping("/del/batch")
        public boolean deleteBatch(@RequestBody List<Integer> ids) { // [1,2,3]
                return userService.removeByIds(ids);
        }

        // 分页查询
        //  接口路径：/user/page?pageNum=1&pageSize=10
        // @RequestParam接受
        //    limit第一个参数 = (pageNum - 1) * pageSize
        // pageSize
        //    @GetMapping("/page")
        //    public Map<String, Object> findPage(@RequestParam Integer pageNum,
        //                                        @RequestParam Integer pageSize,
        //                                        @RequestParam String username) {
        //        pageNum = (pageNum - 1) * pageSize;
        //        username = "%" + username + "%";
        //        List<User> data = userMapper.selectPage(pageNum, pageSize, username);
        //        Integer total = userMapper.selectTotal(username);
        //        Map<String, Object> res = new HashMap<>();
        //        res.put("data", data);
        //        res.put("total", total);
        //        return res;
        //    }

        // 分页查询 - mybatis-plus的方式
        @GetMapping("/page")
        public IPage<User> findPage(@RequestParam Integer pageNum,
                                    @RequestParam Integer pageSize,
                                    @RequestParam(defaultValue = "") String username,
                                    @RequestParam(defaultValue = "") String email,
                                    @RequestParam(defaultValue = "") String address) {
                IPage<User> page = new Page<>(pageNum, pageSize);
                QueryWrapper<User> queryWrapper = new QueryWrapper<>();
                if (!"".equals(username)) {
                        queryWrapper.like("username", username);
                }
                if (!"".equals(email)) {
                        queryWrapper.like("email", email);
                }
                if (!"".equals(address)) {
                        queryWrapper.like("address", address);
                }
                queryWrapper.orderByDesc("id");
                // 1.从缓存中获取数据
                String jsonStr =stringRedisTemplate.opsForValue().get("USER_KEY");
                IPage<User> page1;
                //2.如果缓存为空
                if (StrUtil.isBlank(jsonStr)){
                        // 3.从数据库中获取数据
                        page1 = userService.page(page, queryWrapper);
                        // 4. 存入Redis
                        stringRedisTemplate.opsForValue().set("USER_KEY",JSONUtil.toJsonStr(page1));
                }else {
                        String JsonPage1 =stringRedisTemplate.opsForValue().get("USER_KEY");
                        IPage<User> userIPage = JSONUtil.toBean(JsonPage1, new TypeReference<IPage<User>>() {}, true);
                        return userIPage;
                }
               return page1;
        }

        //导出功能
        @GetMapping("/export")
        public void export(HttpServletResponse response) throws IOException {
                // 从数据库查询出所有的数据
                List<User> list = userService.list();
                // 在内存操作，写出到浏览器，创建一个excel对象
                ExcelWriter writer = ExcelUtil.getWriter(true);
                //自定义标题别名
                writer.addHeaderAlias("username", "用户名");
                writer.addHeaderAlias("password", "密码");
                writer.addHeaderAlias("nickname", "昵称");
                writer.addHeaderAlias("email", "邮箱");
                writer.addHeaderAlias("phone", "电话");
                writer.addHeaderAlias("address", "地址");
                writer.addHeaderAlias("createTime", "创建时间");
                // 一次性写出list内的对象到excel，使用默认样式，强制输出标题
                writer.write(list, true);
                // 设置浏览器响应的格式
                response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
                String fileName = URLEncoder.encode("用户信息", "UTF-8");
                response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
                ServletOutputStream out = response.getOutputStream();
                // 把writer中的数据刷新到输出流对象中
                writer.flush(out, true);
                out.close();
                writer.close();
        }

        //导入功能
        @PostMapping("/import")
        public Boolean imp(MultipartFile file) throws Exception {
                InputStream inputStream = file.getInputStream();
                ExcelReader reader = ExcelUtil.getReader(inputStream);
                // 方式1：(推荐) 通过 javabean的方式读取Excel内的对象，但是要求表头必须是英文，跟javabean的属性要对应起来
                //        List<User> list = reader.readAll(User.class);
                // 方式2：忽略表头的中文，直接读取表的内容
                List<List<Object>> list = reader.read(1);
                List<User> users = CollUtil.newArrayList();
                //遍历list对象（用户信息的集合）
                for (List<Object> row : list) {
                        //每遍历一个具体的用户信息，存入user对象中
                        User user = new User();
                        user.setId(Integer.valueOf(row.get(0).toString()));
                        user.setUsername(row.get(1).toString());
                        user.setPassword(row.get(2).toString());
                        user.setNickname(row.get(3).toString());
                        user.setEmail(row.get(4).toString());
                        user.setPhone(row.get(5).toString());
                        user.setAddress(row.get(6).toString());
                        //再保存数据库
                        users.add(user);
                }
                // 导入的数据插入数据库
                userService.saveBatch(users);
                return true;
        }

        //登录
        @PostMapping("/login")
        public Result login(@RequestBody UserDTO userDTO){
                String username = userDTO.getUsername();
                String password = userDTO.getPassword();
                if (StrUtil.isBlank(username) || StrUtil.isBlank(password)) {
                        return Result.error(Constants.CODE_400,"参数错误");
                }
                UserDTO dto = userService.login(userDTO);
                return Result.success(dto);
        }

        //注册
        @PostMapping("/register")
        public Result register(@RequestBody UserDTO userDTO){
                String username = userDTO.getUsername();
                String password = userDTO.getPassword();
                if (StrUtil.isBlank(username) || StrUtil.isBlank(password)) {
                        return Result.error(Constants.CODE_400,"参数错误");
                }
                User userRegister = userService.register(userDTO);
                return Result.success(userRegister);
        }


        @GetMapping("/username/{username}")
        public Result findByUsername(@PathVariable String username) {
                QueryWrapper<User> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("username", username);
                return Result.success(userService.getOne(queryWrapper));
        }

}
